﻿/*

WinJSYoutube

Author: Philipp Grulich
mail : philippgrulich@hotmail.de

This Class is an JS Port from the PHP Youtube Class written by :  Vikas Patial, http://www.ngcoders.com

*/

"use strict";
WinJS.Namespace.define("Youtube", {
    loadFileUrls: loadFileUrls,

});


var youtubeFileTypes = [
  { itag: "18", format: "MP4", description: "Medium Quality - 480x360", resolution: "480x360" },
  { itag: "22", format: "MP4", description: "High Quality - 1280x720", resolution: "1280x720" },
  { itag: "37", format: "MP4", description: "High Quality - 1920x1080", resolution: "1920x1080" },
  { itag: "38", format: "MP4", description: "High Quality - 4096x230", resolution: "4096x230" }

]


/* Loads all Video Files from a Youtube Video URL
youtubeURL is the url for an youtube Video like:"http://www.youtube.com/watch?v=k_okcNVZqqI"   
resultution is optional. With this value you can set an resulution you with to resive.
If there are no video with this resulution it returns all other.     
*/
function loadFileUrls(youtubeURL, resulution) {
    return new WinJS.Promise(function (comp, err, prog) {
        loadDataFromYoutube(youtubeURL).then(
            function complete(youtubeData) {
                var videoUrls = parsYoutubeData(youtubeData);
                videoUrls = videoUrls.sort(sortfunction);
                if (resulution != null)
                    videoUrls = getVideoWithResulution(resulution, videoUrls)

                comp(videoUrls);

            }


    );


    })
}


// Sorts the by Resulution. The file with the highest resulution is the last file in the array.
function sortfunction(a, b) {
    if (a.itag == b.itag)
        return 0;
    if (a.itag < b.itag)
        return -1
    if( a.itag > b.itag)
        return 1
}

// search a Video with the correct resulution
function getVideoWithResulution(resulution, videoUrls) {
    var rightVideo = null;
    videoUrls.forEach(function (item) {
        if (item.resulution == resulution)
            rightVideo = item;
    });

    if (rightVideo != null)
        return [rightVideo];
    else
        return videoUrls;
};


// search the urls for the video files.
function parsYoutubeData(youtubeData) {

    var reg = new RegExp("stream_map(.[^&]*?)&");
    var match = reg.exec(youtubeData);


    var data = match[1];
    var foundUrls = [];


    var data_array = data.split(",");
    data_array.forEach(function (items, index) {

        var urlsplit = items.split('\\u0026');
        var url = null;
        var sig = null;
        var itag = null;
        urlsplit.forEach(function (urlItem) {

            var index = urlItem.indexOf('=');


            var key = urlItem.substring(0, index);
            var value = urlItem.substring(index + 1);

            switch (key) {
                case "url":
                    url = value;
                    break;
                case "sig":
                    sig = value;
                    break;
                case "itag":
                    itag = value;
                    break;
            }



        });
        if (url != null && sig != null && itag != null) {
            url = decodeURIComponent(url);
            youtubeFileTypes.forEach(function (fileType) {
                if (itag == fileType.itag) {
                    var urlObject = {
                        itag: itag,
                        url: url + '&signature=' + sig,
                        format: fileType.format,
                        description: fileType.description,
                        resulution: fileType.resolution
                    }
                    foundUrls.push(urlObject)
                }
            });

        }
    });
    return foundUrls;
}

// calls the video url.
function loadDataFromYoutube(videoURL) {
    return new WinJS.Promise(function (comp, err, prog) {
        WinJS.xhr({
            type: "GET",
            url: videoURL,
            responseType: "text",

        }).then(function (success) {
            comp(success.response);

        });

    });
};

